package com.cqndt.disaster.device.service.data.impl;

import com.cqndt.disaster.device.dao.data.TabUnionWarnMapper;
import com.cqndt.disaster.device.entity.data.TabUnion;
import com.cqndt.disaster.device.entity.data.TabWarningDevice;
import com.cqndt.disaster.device.entity.data.TabWarningUnite;
import com.cqndt.disaster.device.util.SudasSmsUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 联合告警
 * @author liaohonglai
 * @date 2019/8/6
 */
@Service
@Slf4j
public class TabUnionWarnServiceImpl {

    @Autowired
    private TabUnionWarnMapper tuMapper;

    /**
     * 线程池
     */
    ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5, 20, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

    /**
     * 联合告警定时任务
     */
    @Scheduled(initialDelay = 3000, fixedRate = 60000)
    public void unionWarn() {
        //1.获取任务表数据列表
        List<TabUnion> unionList = tuMapper.getUnionList();
        //1.1 判断任务列表是否为空
        if (unionList.isEmpty()){
            return;
        }
        //2.删除已经执行的任务数据列表
        tuMapper.deleteUnion(unionList);
        //3.循环任务列表
        unionList.forEach(tabUnion -> {
            //3.1 启动多线程执行任务
            poolExecutor.execute(new RunTask(tabUnion));
        });
    }

    /**
     * 多线程执行任务列表任务
     */
    class RunTask implements Runnable {

        private TabUnion tabUnion;

        public RunTask(TabUnion tabUnion) {
            this.tabUnion = tabUnion;
        }

        @Override
        public void run() {
            //4.任务所在联合预警列表
            List<TabWarningUnite> identifyInDevice = tuMapper.getIdentifyInDevice(tabUnion.getIdentify(),tabUnion.getSensorNo());
            //5.判断是否在联合预警设备列表
            if (identifyInDevice.isEmpty()) {
                return;
            }
            //6.循环联合预警列表
            identifyInDevice.forEach(identifyDevice -> {
                //6.1 存储当前联合告警等级
                Set<Integer> set = new HashSet<>();
                //7.判断是否超过阈值
                if (tabUnion.getResult() < identifyDevice.getLevel4()) {
                    return;
                }
                //8.以联合表id查询所有设备数据
                List<TabWarningDevice> uniteIdInDevcie = tuMapper.getUniteIdInDevcie(identifyDevice.getWarningUniteId());
                for (TabWarningDevice device : uniteIdInDevcie) {
                    //9.查询每个设备24小时数据，获取最大值
                    Double maxNumber = 0.0;
                    //9.1 gnss 设备
                    if (device.getDeviceType() == 4) {
                        maxNumber = getGnssMax(device.getIdentify());
                    }
                    //9.2 雨量 设备
                    else if (device.getDeviceType() == 10) {
                        maxNumber = getYlMax(device.getIdentify());
                    }
                    //9.3 其他 设备
                    else {
                        maxNumber = getOtherMax(device.getIdentify(), device.getDeviceNo());
                    }
                    //10.判断是否操作阈值
                    if (maxNumber >= device.getLevel1()) {
                        set.add(1);
                        continue;
                    }
                    if (maxNumber >= device.getLevel2()) {
                        set.add(2);
                        continue;
                    }
                    if (maxNumber >= device.getLevel3()) {
                        set.add(3);
                        continue;
                    }
                    if (maxNumber >= device.getLevel4()) {
                        set.add(4);
                        continue;
                    }
                    //11.如果有任何一个设备或传感器没有超过阈值，结束该联合告警
                    set.clear();
                    break;
                }
                //12.set不为空，说明联合列表得所有设备都告警，发送告警短信，按最低等级发送
                if (!set.isEmpty()) {
                    //按最低等级发送
                    Integer max = Collections.max(set);
                    //短信内容
                    String message = "";
                    switch (max) {
                        case 1:
                            message = identifyDevice.getRedWarning();
                            break;
                        case 2:
                            message = identifyDevice.getOrangeWarning();
                            break;
                        case 3:
                            message = identifyDevice.getYellowWarning();
                            break;
                        case 4:
                            message = identifyDevice.getBlueWarning();
                            break;
                    }
                    //存储告警
                    tuMapper.saveAlarmInfo(max,new Date(),identifyDevice.getWarningUniteId(),message);
                    //更新联合告警，告警时间
                    tuMapper.updateWarning(identifyDevice.getWarningUniteId(),new Date());
                    //获取发送人列
                    String phone = tuMapper.getMsgPerson(max);
                    //如果电话号码为空
                    if (phone==null || "".equals(phone)){
                        return;
                    }
                    //发送短信
                    SudasSmsUtil.send(phone,message);
                    String[] phoneArray = phone.split(",");
                    //记录短信发送记录到列表tab_msg_record
                    tuMapper.saveMsgRecord(phoneArray, message,new Date());
                }
            });
        }
    }

    /**
     * 其他(地裂缝等等)数据24小时历史最大值
     *
     * @param identify
     * @param deviceNo
     * @return
     */
    private Double getOtherMax(String identify, String deviceNo) {
        return tuMapper.getOther24HourMax(identify, deviceNo, new Date());
    }

    /**
     * 获取雨量24小时历史最大值
     *
     * @param identify
     * @return
     */
    private Double getYlMax(String identify) {
        return tuMapper.getYl24HourMax(identify, new Date());
    }

    /**
     * 获取gnss24小时历史最大值
     *
     * @param identify
     * @return
     */
    private Double getGnssMax(String identify) {
        String sensorNo = identify.substring(0, identify.indexOf("@"));
        String sensorType = identify.substring(identify.indexOf("@") + 1);
        return tuMapper.getGnss24HourMax(sensorNo, sensorType, new Date());
    }

}
